<template>
  <div class="page-mark-right">
    <span class="mark-id" v-if="activeCom">Id：{{activeCom.id}}</span>
    <Tabs value="baseAttr" v-if="activeCom">
      <TabPane label="基础属性" name="baseAttr" v-if="Object.keys(activeCom.config).length">
        <!-- 数据源的配置 -->
        <Form class="base-form" :label-width="80" v-show="activeCom.databinding!==null">
          <FormItem label="组件数据源">
            <treeselect
              placeholder="请选择数据源"
              :value="activeCom.databinding ? activeCom.databinding : null"
              :options="sourceTree"
              @select="updateDatabinding"
            />
          </FormItem>
        </Form>

        <Form
          class="base-form"
          :label-width="80"
          v-for="(value,item) in activeCom.config"
          :key="item"
        >
          <!-- 额外配置的在这里显示 -->
          <template v-if="extraConfig[activeCom.name] && extraConfig[activeCom.name][item]">
            <FormItem :label="extraConfig[activeCom.name][item].title" v-show="setConfigShow(item)">
              <!-- 特殊组件-可以选择当前模板中除了自己外的其他所有组件 -->
              <Select
                filterable
                multiple
                :value="value"
                @on-change="v=>{updateCommonValue2(false,v,item)}"
                v-if="extraConfig[activeCom.name][item].componentName === 'idSelect'"
              >
                <Option
                  v-for="(unit,index) of getOtherComponents()"
                  :value="unit.id"
                  :key="index"
                >{{unit.text}}</Option>
              </Select>

              <!-- 特殊组件选择数据源 -->
              <treeselect
                v-if="extraConfig[activeCom.name][item].componentName === 'sourceSelect'"
                placeholder="请选择数据源"
                :value="value"
                :options="sourceTree"
                @select="v=>{updateCommonSource(v,item)}"
              />

              <!-- 下拉框 -->
              <Select
                :value="value"
                @on-change="v=>{updateCommonValue2(false,v,item)}"
                v-if="extraConfig[activeCom.name][item].componentName === 'select'"
              >
                <Option
                  v-for="(unit,index) of extraConfig[activeCom.name][item].options"
                  :value="unit.value"
                  :key="index"
                >{{unit.label}}</Option>
              </Select>

              <!-- 数字框 -->
              <InputNumber
                :value="value"
                @on-change="v=>{updateCommonValue2(false,v,item)}"
                v-if="extraConfig[activeCom.name][item].componentName === 'inputNumber'"
              />

              <!-- 数字框--px -->
              <InputNumber
                :value="parseInt(value)"
                @on-change="v=>{updateCommonValue2(false,v,item,true)}"
                v-if="extraConfig[activeCom.name][item].componentName === 'inputNumberPx'"
              />

              <!-- 输入框 -->
              <Input
                :value="value"
                @on-change="updateCommonValue2($event,value,item)"
                v-if="extraConfig[activeCom.name][item].componentName === 'input'"
              />
              <Input
                type="textarea"
                :value="value"
                :rows="4"
                @on-change="updateCommonValue2($event,value,item)"
                v-if="extraConfig[activeCom.name][item].componentName === 'textarea'"
              />

              <!-- 开关 -->
              <i-switch
                :value="value"
                @on-change="v=>{updateCommonValue2(false,v,item)}"
                v-if="extraConfig[activeCom.name][item].componentName === 'switch'"
              />

              <!-- 数据编辑 -->
              <i
                class="iconfont icon-file-edit"
                title="编辑"
                v-if="extraConfig[activeCom.name][item].componentName === 'jsoneditor'"
                @click="editArray(item)"
              ></i>
            </FormItem>
          </template>

          <!-- 已有组件的在这里显示 -->
          <component v-else :is="item" :value="value" @updateValue="updateCommonValue"></component>
        </Form>

        <!-- 校验的配置 -->
        <Form class="base-form" :label-width="80" v-show="activeCom.valid!==null">
          <FormItem label="组件校验">
            <i class="iconfont icon-file-edit" title="编辑" @click="editValid(activeCom.valid)"></i>
          </FormItem>
        </Form>
      </TabPane>
    </Tabs>

    <Tabs value="styleAttr" v-if="activeCom">
      <TabPane label="样式属性" name="styleAttr" v-if="Object.keys(activeCom.style).length">
        <Form
          class="base-form"
          :label-width="80"
          v-for="(value,item) in activeCom.style"
          :key="item"
        >
          <component :is="item" :value="value" @updateValue="updateStyleValue"></component>
        </Form>
      </TabPane>
    </Tabs>

    <Tabs value="layoutAttr" v-if="activeCom">
      <TabPane label="布局属性" name="layoutAttr">
        <Layout @updateValue="updateLayoutValue" />
      </TabPane>
    </Tabs>

    <!-- <Tabs value="gridAttr" v-if="!activeCom">
      <TabPane label="组件间边距设置" name="gridAttr">
        <Form class="base-form" :label-width="80">
          <FormItem label="水平边距">
            <InputNumber :value="grid.horizontal" @on-change="v=>{updateGrid(v,'horizontal')}" />
          </FormItem>
          <FormItem label="垂直边距">
            <InputNumber :value="grid.vertical" @on-change="v=>{updateGrid(v,'vertical')}" />
          </FormItem>
        </Form>
      </TabPane>
    </Tabs>-->

    <div v-if="!activeCom" class="no-active">设置面板</div>

    <Modal
      width="700px"
      v-model="jsonEditVisual"
      title="数据查看/编辑"
      footer-hide
      class="visual-array-edit-model"
    >
      <Tooltip :content="tooltipContent" :style="toolTipStyle" max-width="400" v-if="editValidFlag">
        数据示例
      </Tooltip>
      <div id="arrayEdit"></div>
      <div class="array-edit-footer">
        <Button @click="cancelHandler" style="margin-right:8px">取消</Button>
        <Button type="primary" @click="okHandler">确定</Button>
      </div>
    </Modal>
  </div>
</template>

<script>
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'

import { iconList } from './config/icon';
import { extraConfig } from './config/extra';
import { deepCopy, typeOf } from 'assets/scripts/common';
import { mapState, mapActions, mapMutations } from 'vuex';

// 可复用组件
import fontFamily from './Right/StyleComponent/FontFamily.vue';
import fontSize from './Right/StyleComponent/FontSize.vue';
import fontWeight from './Right/StyleComponent/FontWeight.vue';
import fontStyle from './Right/StyleComponent/FontStyle.vue';
import textDecoration from './Right/StyleComponent/TextDecoration.vue';
import textAlign from './Right/StyleComponent/TextAlign.vue';
import backgroundColor from './Right/StyleComponent/BackgroundColor.vue';
import color from './Right/StyleComponent/Color.vue';
import borderWidth from './Right/StyleComponent/BorderWidth.vue';
import borderColor from './Right/StyleComponent/BorderColor.vue';
import borderStyle from './Right/StyleComponent/BorderStyle.vue';
import lineHeight from './Right/StyleComponent/lineHeight.vue';
import marginLeft from './Right/StyleComponent/MarginLeft.vue';
import marginRight from './Right/StyleComponent/MarginRight.vue';
import marginTop from './Right/StyleComponent/MarginTop.vue';
import marginBottom from './Right/StyleComponent/MarginBottom.vue';
import paddingLeft from './Right/StyleComponent/PaddingLeft.vue';
import paddingRight from './Right/StyleComponent/PaddingRight.vue';
import paddingTop from './Right/StyleComponent/PaddingTop.vue';
import paddingBottom from './Right/StyleComponent/PaddingBottom.vue';

import Layout from './Right/CommonComponent/Layout.vue';
import placeholder from './Right/CommonComponent/Placeholder.vue';
import disabled from './Right/CommonComponent/Disabled.vue';
import size from './Right/CommonComponent/Size.vue';
import labelName from './Right/CommonComponent/LabelName.vue';
import labelWidth from './Right/CommonComponent/LabelWidth.vue';

export default {
  components: {
    // 样式组件
    fontFamily,
    fontSize,
    fontWeight,
    fontStyle,
    textDecoration,
    textAlign,
    backgroundColor,
    color,
    borderWidth,
    borderColor,
    borderStyle,
    lineHeight,
    marginLeft,
    marginRight,
    marginTop,
    marginBottom,
    paddingLeft,
    paddingRight,
    paddingTop,
    paddingBottom,

    // 基础组件
    Layout,
    placeholder,
    disabled,
    size,
    labelName,
    labelWidth,
    Treeselect
  },

  computed: {
    ...mapState({
      layout: state => state.mark.layout,
      activeCom: state => state.mark.activeCom,
      grid: state => state.mark.grid,
      components: state => state.mark.components,
      sourceTree: state => state.mark.sourceTree
    })
  },

  data () {
    return {
      extraConfig,
      jsonEditVisual: false,
      arrayEditor: null,
      editName: null,
      editValidFlag: false,
      componentNames: {},
      toolTipStyle: {
        position: 'absolute',
        top: 0,
        lineHeight: '46px',
        right: '50px',
        fontSize: '14px',
        fontWeight: 700,
        cursor: 'pointer'
      },
      tooltipContent: '{\n' +
      '"required":true,\n' +
      '"pattern": "",\n' +
      '"min": 1,\n' +
      '"max": 10,\n' +
      '"Length": 10,\n' +
      '"message": "错误信息",\n' +
      '"type": "string"\n' +
      '}'
    };
  },
  methods: {
    ...mapMutations(['setGrid']),
    ...mapActions(['changeActiveCom', 'changeLayoutActiveCom']),

    // 获取除了当前激活组件外的其他组件信息
    getOtherComponents () {
      if (!this.activeCom) {
        return;
      }
      let arr = [];
      let components = JSON.parse(JSON.stringify(this.components))

      components.forEach(item => {
        if (item.id !== this.activeCom.id) {
          item.text = this.componentNames[item.name] + `(${item.id})`;
          arr.push(item);
        }
      });

      return arr;
    },

    // 更新视图的编辑
    updateGrid (v, type) {
      let obj = deepCopy(this.grid);
      obj[type] = v;
      this.setGrid(obj);
    },

    // 配置的显示与否
    setConfigShow (item) {
      if (!this.activeCom || !this.activeCom.name) {
        return;
      }
      let itemConfig = this.extraConfig[this.activeCom.name][item];
      if (!itemConfig.precondition) {
        return true;
      } else {
        let { name, value } = itemConfig.precondition;
        // 当name的值是value的时候才显示
        if (this.activeCom.config[name] === value) {
          return true;
        } else {
          return false;
        }
      }
    },

    // 更改样式的值
    updateStyleValue (item) {
      this.activeCom.style[item.name] = item.value;
      this.changeActiveCom(this.activeCom);
    },

    // 更改布局的值
    updateLayoutValue (activeCom) {
      this.changeLayoutActiveCom(activeCom);
    },

    // 更改普通设置的值
    updateCommonValue (item) {
      // iview表格的columns会自动生产__id，这个要去除，不然会影响渲染
      if (item.name === 'columns' && this.activeCom.name === 'tableItem') {
        item.value.forEach(unit => {
          delete unit.__id;
        });
      }

      this.activeCom.config[item.name] = item.value;
      this.changeActiveCom(this.activeCom);
    },

    updateCommonValue2 (e, value, name, isPx) {
      if (e) {
        value = e.target.value;
      }

      this.updateCommonValue({
        name,
        value: isPx ? value + 'px' : value
      });
    },

    // 更新配置中的数据源
    updateCommonSource (data, name) {
      this.updateCommonValue({
        name,
        value: data.id
      });
    },

    // 更新数据源
    updateDatabinding (data) {
      this.activeCom.databinding = data.id;
      this.changeActiveCom(this.activeCom);
    },

    // 更新校验的值
    updateVaildValue (value) {
      this.activeCom.valid = value;
      this.changeActiveCom(this.activeCom);
    },

    // 校验信息
    editValid (valid) {
      this.jsonEditVisual = true;

      // 表示编辑的是校验信息
      this.editValidFlag = true;

      if (!this.arrayEditor) {
        this.arrayEditor = new this.$jsoneditor(
          document.getElementById('arrayEdit'),
          {
            search: false,
            mode: 'text',
            indentation: 2
          }
        );
      }

      this.arrayEditor.set(valid);
    },

    // 编辑数组/对象
    editArray (name) {
      this.jsonEditVisual = true;
      this.editName = name;

      if (!this.arrayEditor) {
        this.arrayEditor = new this.$jsoneditor(
          document.getElementById('arrayEdit'),
          {
            search: false,
            mode: 'text',
            indentation: 2
          }
        );
      }

      this.arrayEditor.set(this.activeCom.config[name]);
    },

    // 确定编辑
    okHandler () {
      try {
        let value = this.arrayEditor.get();
        // 编辑的是组件的校验信息
        if (this.editValidFlag) {
          if (this.checkData(value)) {
            this.updateVaildValue(value);
          } else {
            return false;
          }
        } else {
          this.updateCommonValue({
            name: this.editName,
            value
          });
        }

        this.cancelHandler();
      } catch (err) {
        console.log(err);
        this.$Message.error('请输入正确的数据');
      }
    },
    // 校验数据格式是否符合规范 value 目标值
    checkData (value) {
      let status = true; // 方法状态
      const that = this;
      const message = '数据格式不符合规范'; // 错误提示
      const typeString = ['min', 'max', 'Length'];
      const original = ['required', 'pattern', 'min', 'max', 'Length', 'message', 'type'];
      const dataType = ['string', 'number', 'boolean', 'object', 'array', 'date', 'float'];
      if (typeOf(value) === 'object') {
        Object.keys(value).every(function (item) {
          if (original.indexOf(item) === -1) {
            status = that.errorNotice(message);
            return status;
          }

          if (item === 'required' && typeOf(value[item]) !== 'boolean') {
            status = that.errorNotice(message);
            return status;
          }

          if (typeString.indexOf(item) > -1 && (typeOf(value[item]) !== 'number' && typeOf(value[item]) !== 'string')) {
            status = that.errorNotice(message);
            return status;
          }

          if (item === 'message' && typeOf(value[item]) !== 'string') {
            status = that.errorNotice(message);
            return status;
          }

          if (item === 'type' && dataType.indexOf(value[item]) === -1) {
            status = that.errorNotice(message);
            return status;
          }
          return true
        })
      } else {
        status = that.errorNotice(message)
      }
      return status;
    },
    // 错误提示并返回
    errorNotice (message) {
      this.$Message.error(message);
      return false;
    },
    // 取消编辑
    cancelHandler () {
      this.jsonEditVisual = false;
      this.editValidFlag = false;
      this.editName = null;
    }
  },
  mounted () {
    iconList.forEach(item => {
      this.componentNames[item.type + 'Item'] = item.text;
    });
  }
};
</script>

<style rel="stylesheet/less" lang="less" scoped>
@import '../../assets/theme/themeBlue.less';
.page-mark-right {
  padding-top: 10px;
  width: 260px;
  position: absolute;
  top: 50px;
  right: 0;
  bottom: 0;
  background: #fff;
  overflow-y: auto;

  .mark-id {
    font-size: 14px;
    float: right;
    padding-right: 4px;
  }

  .ivu-tabs {
    clear: both;
    overflow: auto;
  }

  .no-active {
    text-align: center;
    font-size: 16px;
    color: #999999;
    margin-top: 10px;
  }
  .icon-file-edit {
    cursor: pointer;
    &:hover {
      color: @primary;
    }
  }
}
</style>

<style lang="less">
.visual-array-edit-model {
  .array-edit-footer {
    float: right;
    margin-top: 20px;
  }
  .ivu-modal-body {
    padding-bottom: 72px;
  }
  .jsoneditor-outer {
    height: 400px;
  }
}
.page-mark-right {
  .base-form {
    .ivu-input-wrapper,
    .ivu-input-number,
    .ivu-select,
    .vue-treeselect {
      width: 150px;
    }
  }
}
</style>
